package com.zhanglubao.lol.downloader;

import android.app.NotificationManager;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.os.IBinder;
import android.os.RemoteException;

import com.zhanglubao.lol.config.ZLBConfiguration;
import com.zhanglubao.lol.downloader.util.ConfigUtil;
import com.zhanglubao.lol.downloader.util.Logger;
import com.zhanglubao.lol.downloader.util.SDCardManager;
import com.zhanglubao.lol.util.PlayerUtil;
import com.zhanglubao.lol.util.PreferenceUtil;

import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map.Entry;

/**
 * Created by rocks on 15-6-28.
 */
public class DownloadManager extends BaseDownload {

    private static final String TAG = "Download_Manager";
    private static DownloadManager instance;

    private OnChangeListener listener;

    // 服务接口
    private IDownloadService downloadService;

    /**
     * 已缓存完成的对象列表
     */
    private static HashMap<String, DownloadInfo> downloadedData;

    private ICallback mCallback = new ICallback.Stub() {

        @Override
        public void onChanged(DownloadInfo info)  {

            if (listener != null)
                listener.onChanged(info);
        }

        @Override
        public void onFinish(DownloadInfo info) throws RemoteException {
            if (downloadedData != null)
                downloadedData.put(info.videoid,
                        getDownloadInfoBySavePath(info.savePath));
            if (listener != null)
                listener.onFinish();
        }

        @Override
        public void refresh() throws RemoteException {
            downloadedData = getNewDownloadedData();
        }

    };



    // 服务绑定器
    private ServiceConnection sConnect = new ServiceConnection() {

        @Override
        public void onServiceDisconnected(ComponentName name) {
            Logger.d(TAG, "onServiceDisconnected() called");
        }

        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            // 绑定到服务
            Logger.d(TAG, "onServiceConnected() called");
            downloadService = IDownloadService.Stub.asInterface(service);
            try {
                downloadService.registerCallback(mCallback);
            } catch (RemoteException e) {
                Logger.e(TAG, e);
            }
        }
    };

    public synchronized static DownloadManager getInstance() {
        if (instance == null) {
            Logger.d(TAG, "getInstance()");
            instance = new DownloadManager(ZLBConfiguration.context);
        }
        return instance;
    }

    private DownloadManager(Context context) {
        this.context = context;
        bindService(context);
    }

    private void bindService(Context context) {
        Intent intent = new Intent(context, DownloadService.class);
        context.bindService(intent, sConnect, Context.BIND_AUTO_CREATE);
    }

    public void unregister() {
        try {
            downloadService.unregister();
        } catch (RemoteException e) {
            Logger.e(TAG, e);
        }catch (Exception e) {
            Logger.e(TAG, e);
        }
    }

    public void setOnChangeListener(OnChangeListener listener) {
        this.listener = listener;
    }



    @SuppressWarnings("unchecked")
    @Override
    public HashMap<String, DownloadInfo> getDownloadingData() {
        if (downloadService != null) {
            try {
                return (HashMap<String, DownloadInfo>) downloadService
                        .getDownloadingData();
            } catch (RemoteException e) {
                Logger.e(TAG, e);
            }
        }

        HashMap<String, DownloadInfo> downloadingData = new HashMap<String, DownloadInfo>();
        if (sdCard_list == null
                && (sdCard_list = SDCardManager.getExternalStorageDirectory()) == null) {
            return downloadingData;
        }
        for (int j = 0; j < sdCard_list.size(); j++) {
            File dir = new File(sdCard_list.get(j).path +ConfigUtil.getDownloadPath());
            if (!dir.exists())
                continue;
            String[] dirs = dir.list();
            for (int i = dirs.length - 1; i >= 0; i--) {
                String vid = dirs[i];
                DownloadInfo info = getDownloadInfoBySavePath(sdCard_list
                        .get(j).path + ConfigUtil.getDownloadPath() + vid + "/");
                if (info != null
                        && info.getState() != DownloadInfo.STATE_FINISH
                        && info.getState() != DownloadInfo.STATE_CANCEL) {

                    downloadingData.put(info.taskId, info);
                }
            }
        }
        return downloadingData;
    }

    /**
     * 已经完成的视频缓存列表
     *
     * @return Map<String, DownloadInfo>
     */
    public HashMap<String, DownloadInfo> getDownloadedData() {
        downloadedData = getNewDownloadedData();
        return downloadedData;
    }

    private HashMap<String, DownloadInfo> getNewDownloadedData() {
        downloadedData = new HashMap<String, DownloadInfo>();
        if ((sdCard_list = SDCardManager.getExternalStorageDirectory()) == null) {
            return downloadedData;
        }
        for (int j = 0; j < sdCard_list.size(); j++) {
            File dir = new File(sdCard_list.get(j).path + ConfigUtil.getDownloadPath());
            if (!dir.exists())
                continue;
            String[] dirs = dir.list();
            for (int i = dirs.length - 1; i >= 0; i--) {
                String vid = dirs[i];
                final DownloadInfo d = getDownloadInfoBySavePath(sdCard_list
                        .get(j).path + ConfigUtil.getDownloadPath() + vid + "/");
                if (d != null && d.getState() == DownloadInfo.STATE_FINISH) {
                    downloadedData.put(d.videoid, d);
                    if (d.segCount != d.segsSeconds.length) {
                        new Thread() {
                            public void run() {
                                try {
                                    DownloadUtils.getDownloadData(d);
                                    downloadedData.put(d.videoid, d);
                                    DownloadUtils.makeDownloadInfoFile(d);
                                    DownloadUtils.makeM3U8File(d);
                                } catch (Exception e) {
                                }
                            };
                        }.start();
                    }
                }
            }
        }
        return downloadedData;
    }

    public ArrayList<DownloadInfo> getDownloadedList() {
        ArrayList<DownloadInfo> list = new ArrayList<DownloadInfo>();
        Iterator iter = getDownloadedData().entrySet().iterator(); // 获得map的Iterator
        while (iter.hasNext()) {
            Entry entry = (Entry) iter.next();
            list.add((DownloadInfo) entry.getValue());
        }
        return list;
    }

    /**
     * TODO 根据showid和集数号查本地视频，为null则不存在
     */
    @SuppressWarnings("rawtypes")
    public DownloadInfo getDownloadInfo(String showId, int show_videoseq) {
        if (showId == null)
            return null;
        Iterator iter = getDownloadedData().entrySet().iterator(); // 获得map的Iterator
        while (iter.hasNext()) {
            Entry entry = (Entry) iter.next();
            DownloadInfo info = (DownloadInfo) entry.getValue();
            if ( info.getState() != DownloadInfo.STATE_CANCEL) {
                return info;
            }
        }
        return null;
    }

    @SuppressWarnings("rawtypes")
    public ArrayList<DownloadInfo> getDownloadInfoListById(
            String videoIdOrShowId) {
        if (videoIdOrShowId == null) {
            return null;
        }
        ArrayList<DownloadInfo> list = null;
        if (getDownloadedData().containsKey(videoIdOrShowId)) {
            if (list == null)
                list = new ArrayList<DownloadInfo>();
            list.add(getDownloadedData().get(videoIdOrShowId));
        } else {
            Iterator iter = getDownloadedData().entrySet().iterator(); // 获得map的Iterator
            while (iter.hasNext()) {
                Entry entry = (Entry) iter.next();
                DownloadInfo info = (DownloadInfo) entry.getValue();

            }
            if (list != null && list.size() > 1) {
                DownloadInfo.compareBySeq = true;// 按剧集排序
                Collections.sort(list);// 排序
            }
        }
        return list;
    }
    /**
     * TODO Comment：获得本地下一集视频的相关信息
     *
     * @return DownloadInfo下一个视频信息, 若无下一集则返回null
     */
    @SuppressWarnings("rawtypes")
    public DownloadInfo getNextDownloadInfo(String videoId) {
        DownloadInfo thisinfo = getDownloadInfo(videoId);
        ArrayList<DownloadInfo> temp = new ArrayList<DownloadInfo>();
        Iterator iter = getDownloadedData().entrySet().iterator(); // 获得map的Iterator

        if (thisinfo == null)
            return null;
        boolean isthis = false;
        if (thisinfo.isSeries()) {// 是剧集
            while (iter.hasNext()) {
                Entry entry = (Entry) iter.next();
                DownloadInfo info = (DownloadInfo) entry.getValue();
                if (info.albumid.equals(thisinfo.albumid)) {
                    temp.add(info);
                }
            }
            DownloadInfo.compareBySeq = true;// 按剧集排序
            Collections.sort(temp);// 排序
            for (DownloadInfo info : temp) {
                if (isthis) {
                    return info;
                } else if (info.videoid.equals(videoId)) {
                    isthis = true;
                }
            }
        } else {// 非剧集
            while (iter.hasNext()) {
                Entry entry = (Entry) iter.next();
                DownloadInfo info = (DownloadInfo) entry.getValue();
                temp.add(info);
            }
            DownloadInfo.compareBySeq = false;// 按时间排序
            Collections.sort(temp);// 排序
            for (DownloadInfo info : temp) {
                if (isthis && !info.isSeries()) {
                    return info;
                } else if (thisinfo.videoid.equals(info.videoid)) {
                    isthis = true;
                }
            }
        }
        return null;
    }

    /**
     * 根据showId获得已缓存的视频数
     *
     * @param showId
     * @return
     */
    @SuppressWarnings("rawtypes")
    public int getHowManyDownloadsByShowId(String showId) {
        if (showId == null || showId.length() == 0)
            return 0;
        int count = 0;
        Iterator iter = getDownloadedData().entrySet().iterator(); // 获得map的Iterator
        while (iter.hasNext()) {
            Entry entry = (Entry) iter.next();
            DownloadInfo info = (DownloadInfo) entry.getValue();
            if (showId.equals(info.albumid)) {
                count++;
            }
        }
        return count;
    }

    private OnCreateDownloadListener lis = null;

    /**
     * TODO 创建下载任务
     */
    public void createDownload(String videoId, String videoName, String imgUrl,
                               OnCreateDownloadListener listener) {
        setOnCreateDownloadListener(listener);
        try {
            downloadService.createDownload(videoId, videoName, imgUrl);
        }   catch (RemoteException e) {
            Logger.e(TAG, e);
        }
    }

    /**
     * TODO 创建下载任务(批量)
     */
    public void createDownloads(String[] videoIds, String[] videoNames, String[] imgUrls,
                                OnCreateDownloadListener listener) {
        setOnCreateDownloadListener(listener);
        try {
            downloadService.createDownloads(videoIds, videoNames, imgUrls);
        } catch (RemoteException e) {
            Logger.e(TAG, e);
        }
    }

    private void setOnCreateDownloadListener(OnCreateDownloadListener listener) {
        lis = listener;
        if (listener == null) {
            return;
        }
        OnCreateDownloadReceiver on = new OnCreateDownloadReceiver() {
            @Override
            public void onOneReady() {
                if (lis != null)
                    lis.onOneReady();
            }

            @Override
            public void onOneFailed() {
                if (lis != null)
                    lis.onOneFailed();
            }

            @Override
            public void onfinish(boolean isNeedRefresh) {
                if (lis != null)
                    lis.onfinish(isNeedRefresh);
                lis = null;
            }
        };
        IntentFilter filter = new IntentFilter();
        filter.addAction(ACTION_CREATE_DOWNLOAD_ONE_READY);
        filter.addAction(ACTION_CREATE_DOWNLOAD_ONE_FAILED);
        filter.addAction(ACTION_CREATE_DOWNLOAD_ALL_READY);
        ZLBConfiguration.context.registerReceiver(on, filter);
    }

    public abstract class OnCreateDownloadReceiver extends BroadcastReceiver {

        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            if (IDownload.ACTION_CREATE_DOWNLOAD_ONE_READY.equals(action)) {
                Logger.d("Download_OnCreateDownloadListener", "onOneReady()");
                onOneReady();
            } else if (IDownload.ACTION_CREATE_DOWNLOAD_ALL_READY
                    .equals(action)) {
                boolean value = intent.getBooleanExtra(
                        IDownload.KEY_CREATE_DOWNLOAD_IS_NEED_REFRESH, true);
                Logger.d("Download_OnCreateDownloadListener", "onAllReady():"
                        + value);
                onfinish(value);
            } else if (IDownload.ACTION_CREATE_DOWNLOAD_ONE_FAILED
                    .equals(action)) {
                Logger.d("Download_OnCreateDownloadListener", "onOneFailed()");
                onOneFailed();
            }
        }

        /**
         * 当每一个下载已准备的时候
         */
        public abstract void onOneReady();

        /**
         * 当每一个下载失败
         */
        public abstract void onOneFailed();

        /**
         * 当全部下载已准备的时候
         *
         * @param isNeedRefresh 是否需要刷新数据
         */
        public abstract void onfinish(boolean isNeedRefresh);

    }

    @Override
    public void startDownload(String taskId) {
        try {

            downloadService.down(taskId);
        } catch (Exception e) {
            Logger.e(TAG, e);
        }
    }

    @Override
    public void pauseDownload(String taskId) {
        try {
            downloadService.pause(taskId);
        } catch (Exception e) {
            Logger.e(TAG, e);
        }
    }

    @Override
    public void refresh() {
        try {
            downloadService.refresh();
        } catch (Exception e) {
            Logger.e(TAG, e);
        }
    }

    @Override
    public void startNewTask() {
        Intent i = new Intent(context, DownloadService.class);
        i.setAction(DownloadService.ACTION_STAER_NEWTASK);
        context.startService(i);
    }


    @Override
    public void stopAllTask() {
        try {
            downloadService.stopAllTask();
        } catch (Exception e) {
            Logger.e(TAG, e);
        }
    }

    @Override
    public boolean deleteDownloading(String taskId) {
        Logger.d(TAG, "deleteDownloading() :" + taskId);
        try {
            downloadService.delete(taskId);
        } catch (Exception e) {
            Logger.e(TAG, e);
        }
        return false;
    }

    @Override
    public boolean deleteAllDownloading() {
        Logger.d(TAG, "deleteAllDownloading()");
        try {
            return downloadService.deleteAll();
        } catch (Exception e) {
            Logger.e(TAG, e);
        }
        return false;
    }

    public boolean deleteDownloaded(final DownloadInfo info) {
        Logger.d(TAG, "deleteDownloaded() :" + info.title);
        // info.setState(DownloadInfo.STATE_CANCEL);
        downloadedData.remove(info.videoid);
        if (PreferenceUtil.getPreference(KEY_LAST_NOTIFY_TASKID).equals(info.taskId)) {
            NotificationManager nm = (NotificationManager) context
                    .getSystemService(Context.NOTIFICATION_SERVICE);
            nm.cancel(NOTIFY_ID);
            PreferenceUtil.savePreference(KEY_LAST_NOTIFY_TASKID, "");
        }
        new Thread() {
            public void run() {
                PlayerUtil.deleteFile(new File(info.savePath));
            }

            ;
        }.start();
        startNewTask();
        return true;
    }

    public boolean deleteDownloadeds(final ArrayList<DownloadInfo> infos) {
        Logger.d(TAG, "deleteDownloadeds() : ArrayList");
        if (infos == null || infos.size() == 0)
            return true;
        String nId = PreferenceUtil.getPreference(KEY_LAST_NOTIFY_TASKID);
        for (DownloadInfo info : infos) {
            downloadedData.remove(info.videoid);
            if (nId.equals(info.taskId)) {
                NotificationManager nm = (NotificationManager) context
                        .getSystemService(Context.NOTIFICATION_SERVICE);
                nm.cancel(NOTIFY_ID);
                PreferenceUtil.savePreference(KEY_LAST_NOTIFY_TASKID, "");
            }
        }


        new Thread() {
            public void run() {
                for (DownloadInfo info : infos) {
                    PlayerUtil.deleteFile(new File(info.savePath));
                }
            }

            ;
        }.start();
        return true;
    }

    @SuppressWarnings({"rawtypes", "unchecked"})
    public boolean deleteAllDownloaded() {
        Logger.d(TAG, "deleteAllDownloaded()");
        if (getDownloadedData().size() == 0)
            return true;
        final HashMap<String, DownloadInfo> clone = (HashMap<String, DownloadInfo>) getDownloadedData()
                .clone();
        String nId = PreferenceUtil.getPreference(KEY_LAST_NOTIFY_TASKID);
        Iterator iter = getDownloadedData().entrySet().iterator(); // 获得map的Iterator
        while (iter.hasNext()) {
            Entry entry = (Entry) iter.next();
            DownloadInfo info = (DownloadInfo) entry.getValue();
            if (nId.equals(info.taskId)) {
                NotificationManager nm = (NotificationManager) context
                        .getSystemService(Context.NOTIFICATION_SERVICE);
                nm.cancel(NOTIFY_ID);
                PreferenceUtil.savePreference(KEY_LAST_NOTIFY_TASKID, "");
            }
        }
        new Thread() {
            public void run() {
                Iterator iter = clone.entrySet().iterator();
                while (iter.hasNext()) {
                    Entry entry = (Entry) iter.next();
                    DownloadInfo info = (DownloadInfo) entry.getValue();
                    PlayerUtil.deleteFile(new File(info.savePath));
                }
            }

            ;
        }.start();
        getDownloadedData().clear();
        return true;
    }

    @Override
    public final String getCurrentDownloadSDCardPath() {
        try {
            return downloadService.getCurrentDownloadSDCardPath();
        } catch (Exception e) {
            Logger.e(TAG, e);
        }
        return PreferenceUtil.getPreference("download_file_path",
                SDCardManager.getDefauleSDCardPath());
    }

    @Override
    public void setCurrentDownloadSDCardPath(String path) {
        try {
            downloadService.setCurrentDownloadSDCardPath(path);
        } catch (Exception e) {
            Logger.e(TAG, e);
        }

    }

    @Override
    public boolean canUse3GDownload() {
        try {
            return downloadService.canUse3GDownload();
        } catch (Exception e) {
            Logger.e(TAG, e);
        }
        return PreferenceUtil.getPreferenceBoolean("allowCache3G", false);
    }

    @Override
    public void setCanUse3GDownload(boolean flag) {
        try {
            downloadService.setCanUse3GDownload(flag);
        } catch (Exception e) {
            Logger.e(TAG, e);
        }
    }


    @Override
    public int getDownloadFormat() {
        try {
            return downloadService.getDownloadFormat();
        } catch (Exception e) {
            Logger.e(TAG, e);
        }
        return DownloadUtils.getDownloadFormat();
    }

    @Override
    public void setDownloadFormat(int format) {
        DownloadUtils.setDownloadFormat(format);
        try {
            downloadService.setDownloadFormat(format);
        } catch (Exception e) {
            Logger.e(TAG, e);
        }
    }


    public void setTimeStamp(long time) {
        try {
            downloadService.setTimeStamp(time);
        } catch (Exception e) {
            Logger.e(TAG, e);
        }
    }


}
